package org.finesys.common.core.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import lombok.experimental.UtilityClass;
import org.springframework.util.CollectionUtils;

import javax.validation.*;
import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * 校验工具类
 */
@UtilityClass
public class ValidationUtil {

    private static ValidatorFactory VALIDATOR_FACTORY = Validation.buildDefaultValidatorFactory();

    /**
     * 校验参数信息
     */
    public <T> void validateParam(T t, Class<?>... groups) {
        Validator validator = VALIDATOR_FACTORY.getValidator();
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(t, groups);
        if (!CollectionUtils.isEmpty(constraintViolations)) {
            throw new ConstraintViolationException(constraintViolations);
        }
    }

    /**
     * 验证参数对象 如果验证失败则返回所有失败信息
     */
    public <T> String validate(T t, Class<?>... groups) {
        Validator validator = VALIDATOR_FACTORY.getValidator();
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(t, groups);
        StringBuilder sb = new StringBuilder();
        for (ConstraintViolation<T> constraintViolation : constraintViolations) {
            sb.append(constraintViolation.getMessage()).append(System.lineSeparator());
        }
        return sb.toString();
    }

    /**
     * 验证参数对象 验证失败则抛出异常
     */
    public void validateListObject(List<?> list, Class<?>... groups) {
        if (CollectionUtil.isEmpty(list)) {
            return;
        }

        Validator validator = VALIDATOR_FACTORY.getValidator();
        list.forEach(object -> {
            Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
            if (CollUtil.isNotEmpty(constraintViolations)) {
                throw new ConstraintViolationException(constraintViolations);
            }
        });
    }

    public static <T> T ensureNotNull(T objectName, String name) {
        return ensureNotNull(objectName, "%s can not null", name);
    }

    public static <T> T ensureNotNull(T objectName, String format, Object... args) {
        if (objectName == null) {
            throw new IllegalArgumentException(String.format(format, args));
        }
        return objectName;
    }

    public static String ensureNotBlank(String string, String name) {
        if (string != null && !string.trim().isEmpty()) {
            return string;
        } else {
            throw new IllegalArgumentException(String.format("%s cannot be null or blank", name));
        }
    }

    public static int ensureGreaterThanZero(Integer value, String name) {
        if (value <= 0) {
            throw new IllegalArgumentException(String.format("%s must greater than zero", name));
        }
        return value;
    }

    public static double ensureBetween(Double value, double minValue, double maxValue, String name) {
        if (value == null || value < minValue || value > maxValue) {
            throw new IllegalArgumentException(name + " must between " + minValue + " and " + maxValue + ",but is " + value);
        }
        return value;
    }

    public static int ensureBetween(Integer value, int minValue, int maxValue, String name) {
        if (value == null || value < minValue || value > maxValue) {
            throw new IllegalArgumentException(name + " must between " + minValue + " and " + maxValue + ",but is " + value);
        }
        return value;
    }

    public static long ensureBetween(Long value, long minValue, long maxValue, String name) {
        if (value == null || value < minValue || value > maxValue) {
            throw new IllegalArgumentException(name + " must between " + minValue + " and " + maxValue + ",but is " + value);
        }
        return value;
    }

    public static <T extends Collection<?>> T ensureNotEmpty(T comparisonValues, String name) {
        if (comparisonValues != null && !comparisonValues.isEmpty()) {
            return comparisonValues;
        }
        throw new IllegalArgumentException(name + " can not empty");
    }

    public static void ensureTrue(boolean expression, String msg) {
        if (!expression) {
            throw new IllegalArgumentException(msg);
        }
    }

}
